// 对axios进行二次封装
// 此文件作用: 封装一个网络请求的工具对象
// 项目会有多个页面(.vue文件), 不能每个文件都去配置一遍公共代码
// 此文件就是把公共的东西抽离放到这里

import axios from 'axios'
import { Message } from 'element-ui'
import JSONbig from 'json-bigint'
import to from './awaitTo'
const ajax = axios.create({ // 生成自定义axios对象
  baseURL: 'http://api-toutiao-web.itheima.net',
  // 作用: 所有的网路请求, 都会在前面拼接这个地址
  // 使用场景: 统一项目的基础地址(如果有某个地址不一样再去覆盖就可以了)
  // 特殊: 具体请求的时候, 如果有baseURL就会覆盖全局这个
  transformResponse: [function (data) { // 对内容进行处理
    // data:就是本次请求获取的数据
    // 在这里可以对它进行进一步的处理 -- JSONbig
    // 后端返回数据可能不是 JSON 字符串，而JSONbig.parse()只能处理JSON字符串
    // 所以，为了保证代码可以正常执行，这里引入try-catch来捕获异常
    try {
      // 如果没有遇到错误，就返回 JSONbig处理之后的数据
      return JSONbig.parse(data) // return给调用的地方把数据传出去
    } catch (err) {
      // console.error('JSONbig转换出错', err) // error红色的打印提示
      return data
    }
  }]
})
// 报错是axios内部抛出错误到控制台上 - 拦截一下axios响应过程(手动处理错误提示)
// (请求过程): 用户 -> 方法 -> 调用API方法 -> axios -> 请求拦截器(发起请求之前做些处理) -> ajax发起网络请求(目标url)
// (响应过程): 逻辑代码 <- await  <- 响应拦截器(预处理,再决定)  <- axios <- 后端会把数据响应返回
// 添加请求拦截器
ajax.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么 -- 带请求头Authorization字段和值
  config.headers.Authorization = 'Bearer ' + sessionStorage.getItem('token')
  // 有的接口不需要Authorization
  // 如果后端不敏感(是否判断不必要的请求头)(就无所谓)
  // 如果后端有的地址不让传Authorization
  // 例如: 登录的接口, 不要带Authorization
  // if (config.url !== '/mp/v1_0/authorizations') {
  //   config.headers.Authorization = 'Bearer ' + sessionStorage.getItem('token')
  // }
  return config
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})
// 添加响应拦截器
ajax.interceptors.response.use(function (response) { // http响应状态码 为2xx / 3xx开头(成功)的进入这里
  // 对响应数据做点什么
  return response // 直接返回给await地方
}, function (error) { // http响应状态码 4xx/5xx开头就直接进入这个函数体
  // 对响应错误做点什么 - 来一个错误提示的弹窗给用户提示  (这里的this不是Vue对象)
  // console.dir(error)
  const errTextObj = { // 自己写的中英文对照(后台给的错误提示太....了)
    'Please verify your real information in app.': '手机号只能用固定的',
    'Invalid code.': '验证码错误',
    'User must be authorized.': '身份验证失败',
    'Invalid cover param.': '封面图片有问题_请根据选择的数量传递'
  }

  let messageKey // 取出后台返回的message提示消息
  if (typeof error.response.data.message === 'object') {
    messageKey = error.response.data.message.cover
  } else {
    messageKey = error.response.data.message
  }

  Message({
    message: errTextObj[messageKey], // 取出中文显示
    type: 'error',
    onClose () { // 等待弹窗消失了, 再执行这里代码
      // 只有401错误-身份失败必须回到登录页, 其他的错误可以留在原地 (this不是vue对象不能用路由跳转)
      if (error.response.status === 401) {
        sessionStorage.clear() // 你的token非法/过期清除掉
        window.location.href = '/#/login' // 回到/路径路由是/login
      }
    }
  })

  return Promise.reject(error) // 直接返回一个Promise错误对象-await无法接受, 直接把错误抛出到控制台显示
})

export default function (obj) { // 外面request(传入具体的请求参数对象)
  // 内部还是要调用自定义axios对象ajax发起请求
  const promiseByAxios = ajax(obj)
  return to(promiseByAxios) // 换一个被加工了的新的Promise对象 (await 用这个新的Promise就能在未来)
  // 拿到一个数组既有成功的元素 也有失败的结果
}

// 外部引入
// import request from '路径/utils/request.js'
// 使用

//  *  request({
//  *      url: "/具体的路径",
//  *      method: "POST",
//  *      data: 请求体传参
//  *  })
